﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Krile.Common.Suggestor
{
    public partial class SuggestList : Form
    {
        private class DisplayItem
        {
            public DisplayItem(string key)
                : this(key, null) { }

            public DisplayItem(string key, string value)
                : this(key, value, "{0}:{1}") { }

            public DisplayItem(string key, string value, string format)
            {
                this.Item = key;
                this.Desc = value;
                this.Format = format;
            }

            public string Item { get; set; }

            public string Desc { get; set; }

            public string Format = "{0}:{1}";

            public override string ToString()
            {
                if (String.IsNullOrEmpty(Desc))
                    return Item;
                if (String.IsNullOrEmpty(Format))
                    return Item + ":" + Desc;
                else
                    return String.Format(Format, Item, Desc);
            }
        }

        public event Action OnApplied;

        SuggestableTextBoxCore parent;
        public SuggestList(SuggestableTextBox owner, Point location)
        {
            InitializeComponent();
            parent = owner.TextCore;
            location.Y += 4; // margin
            this.Location = location;
        }

        public void SetItem(IEnumerable<string> items)
        {
            this.candidateList.Items.Clear();
            if (items == null)
                throw new ArgumentNullException("items");
            foreach (var i in items)
            {
                this.candidateList.Items.Add(new DisplayItem(i));
            }
        }

        public void SetItem(IEnumerable<KeyValuePair<string, string>> items)
        {
            SetItem(items, null);
        }

        public void SetItem(IEnumerable<KeyValuePair<string, string>> items, string format)
        {
            this.candidateList.Items.Clear();
            if (items == null)
                throw new ArgumentNullException("items");
            foreach (var i in items)
            {
                this.candidateList.Items.Add(new DisplayItem(i.Key, i.Value, format));
            }
        }

        private void SuggestList_KeyDown(object sender, KeyEventArgs e)
        {
            parent.Focus();
        }

        private void SuggestList_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            parent.Focus();
        }

        private void SuggestList_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (notClose)
            {
                e.Cancel = true;
                parent.Focus();
            }
        }

        public string GetNearestCandidate()
        {
            if (candidateList.SelectedIndex < 0)
                return null;
            else
            {
                var di = (DisplayItem)candidateList.Items[candidateList.SelectedIndex];
                if (di != null)
                    return di.Item;
                else
                    return null;
            }
        }

        public void UpdateSearchTargets(string inputted)
        {
            int selected = -1;
            for (int i = 0; i < candidateList.Items.Count; i++)
            {
                System.Diagnostics.Debug.WriteLine(inputted);
                if (((DisplayItem)candidateList.Items[i]).Item.StartsWith(inputted, StringComparison.CurrentCultureIgnoreCase))
                {
                    selected = i;
                    break;
                }
            }
            candidateList.SelectedIndex = selected;
        }

        bool notClose = true;
        public void SuggestClose()
        {
            notClose = false;
            this.Close();
        }

        public void MoveSelectionIndex(bool up)
        {
            if (candidateList.SelectedIndex >= 0)
            {
                if (up && candidateList.SelectedIndex > 0)
                    candidateList.SelectedIndex--;
                else if (!up && candidateList.SelectedIndex < candidateList.Items.Count - 1)
                    candidateList.SelectedIndex++;
            }
        }

        private void candidateList_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (OnApplied != null)
                OnApplied.Invoke();
        }
    }
}
